home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / Python 1.1 / Lib / mimetools.py < prev    next >
Encoding:
Python Source  |  1994-08-01  |  4.2 KB  |  187 lines  |  [TEXT/R*ch]

  1. # Various tools used by MIME-reading or MIME-writing programs.
  2.  
  3.  
  4. import os
  5. import rfc822
  6. import string
  7. import tempfile
  8.  
  9.  
  10. # A derived class of rfc822.Message that knows about MIME headers and
  11. # contains some hooks for decoding encoded and multipart messages.
  12.  
  13. class Message(rfc822.Message):
  14.  
  15.     def __init__(self, fp):
  16.         rfc822.Message.__init__(self, fp)
  17.         self.encodingheader = \
  18.             self.getheader('content-transfer-encoding')
  19.         self.typeheader = \
  20.             self.getheader('content-type')
  21.         self.parsetype()
  22.         self.parseplist()
  23.  
  24.     def parsetype(self):
  25.         str = self.typeheader
  26.         if str == None:
  27.             str = 'text/plain'
  28.         if ';' in str:
  29.             i = string.index(str, ';')
  30.             self.plisttext = str[i:]
  31.             str = str[:i]
  32.         else:
  33.             self.plisttext = ''
  34.         fields = string.splitfields(str, '/')
  35.         for i in range(len(fields)):
  36.             fields[i] = string.lower(string.strip(fields[i]))
  37.         self.type = string.joinfields(fields, '/')
  38.         self.maintype = fields[0]
  39.         self.subtype = string.joinfields(fields[1:], '/')
  40.  
  41.     def parseplist(self):
  42.         str = self.plisttext
  43.         self.plist = []
  44.         while str[:1] == ';':
  45.             str = str[1:]
  46.             if ';' in str:
  47.                 # XXX Should parse quotes!
  48.                 end = string.index(str, ';')
  49.             else:
  50.                 end = len(str)
  51.             f = str[:end]
  52.             if '=' in f:
  53.                 i = string.index(f, '=')
  54.                 f = string.lower(string.strip(f[:i])) + \
  55.                     '=' + string.strip(f[i+1:])
  56.             self.plist.append(string.strip(f))
  57.  
  58.     def getplist(self):
  59.         return self.plist
  60.  
  61.     def getparam(self, name):
  62.         name = string.lower(name) + '='
  63.         n = len(name)
  64.         for p in self.plist:
  65.             if p[:n] == name:
  66.                 return rfc822.unquote(p[n:])
  67.         return None
  68.  
  69.     def getencoding(self):
  70.         if self.encodingheader == None:
  71.             return '7bit'
  72.         return string.lower(self.encodingheader)
  73.  
  74.     def gettype(self):
  75.         return self.type
  76.  
  77.     def getmaintype(self):
  78.         return self.maintype
  79.  
  80.     def getsubtype(self):
  81.         return self.subtype
  82.  
  83.  
  84.  
  85.  
  86. # Utility functions
  87. # -----------------
  88.  
  89.  
  90. # Return a random string usable as a multipart boundary.
  91. # The method used is so that it is *very* unlikely that the same
  92. # string of characters will every occur again in the Universe,
  93. # so the caller needn't check the data it is packing for the
  94. # occurrence of the boundary.
  95. #
  96. # The boundary contains dots so you have to quote it in the header.
  97.  
  98. _prefix = None
  99.  
  100. def choose_boundary():
  101.     global _generation, _prefix, _timestamp
  102.     import time
  103.     import rand
  104.     if _prefix == None:
  105.         import socket
  106.         import os
  107.         hostid = socket.gethostbyname(socket.gethostname())
  108.         uid = `os.getuid()`
  109.         pid = `os.getpid()`
  110.         seed = `rand.rand()`
  111.         _prefix = hostid + '.' + uid + '.' + pid
  112.     timestamp = `int(time.time())`
  113.     seed = `rand.rand()`
  114.     return _prefix + '.' + timestamp + '.' + seed
  115.  
  116.  
  117. # Subroutines for decoding some common content-transfer-types
  118.  
  119. # XXX This requires that uudecode and mmencode are in $PATH
  120.  
  121. def decode(input, output, encoding):
  122.     if decodetab.has_key(encoding):
  123.         pipethrough(input, decodetab[encoding], output)
  124.     else:
  125.         raise ValueError, \
  126.               'unknown Content-Transfer-Encoding: %s' % encoding
  127.  
  128. def encode(input, output, encoding):
  129.     if encodetab.has_key(encoding):
  130.         pipethrough(input, encodetab[encoding], output)
  131.     else:
  132.         raise ValueError, \
  133.               'unknown Content-Transfer-Encoding: %s' % encoding
  134.  
  135. uudecode_pipe = '''(
  136. TEMP=/tmp/@uu.$$
  137. sed "s%^begin [0-7][0-7]* .*%begin 600 $TEMP%" | uudecode
  138. cat $TEMP
  139. rm $TEMP
  140. )'''
  141.  
  142. decodetab = {
  143.     'uuencode':        uudecode_pipe,
  144.     'x-uuencode':        uudecode_pipe,
  145.     'quoted-printable':    'mmencode -u -q',
  146.     'base64':        'mmencode -u -b',
  147. }
  148.  
  149. encodetab = {
  150.     'x-uuencode':        'uuencode tempfile',
  151.     'uuencode':        'uuencode tempfile',
  152.     'quoted-printable':    'mmencode -q',
  153.     'base64':        'mmencode -b',
  154. }
  155.  
  156. def pipeto(input, command):
  157.     pipe = os.popen(command, 'w')
  158.     copyliteral(input, pipe)
  159.     pipe.close()
  160.  
  161. def pipethrough(input, command, output):
  162.     tempname = tempfile.mktemp()
  163.     try:
  164.         temp = open(tempname, 'w')
  165.     except IOError:
  166.         print '*** Cannot create temp file', `tempname`
  167.         return
  168.     copyliteral(input, temp)
  169.     temp.close()
  170.     pipe = os.popen(command + ' <' + tempname, 'r')
  171.     copybinary(pipe, output)
  172.     pipe.close()
  173.     os.unlink(tempname)
  174.  
  175. def copyliteral(input, output):
  176.     while 1:
  177.         line = input.readline()
  178.         if not line: break
  179.         output.write(line)
  180.  
  181. def copybinary(input, output):
  182.     BUFSIZE = 8192
  183.     while 1:
  184.         line = input.read(BUFSIZE)
  185.         if not line: break
  186.         output.write(line)
  187.